package com.aiwiown.snackmq.api;

import com.aiwiown.snackmq.api.exception.SnackMQClientException;
import com.aiwiown.snackmq.common.message.Message;

/**
 * 事务消息生产者接口。
 * <p>
 * 它扩展了普通的 Producer 接口，增加了发送事务消息和设置状态回查监听器的能力。
 * </p>
 */
public interface TransactionalProducer extends Producer {

    /**
     * 在一个事务中发送消息。
     * <p>
     * 这个过程包括三个步骤：
     * 1. 发送一个 "半消息" (prepare message) 到 Broker。
     * 2. 执行本地事务 (由 LocalTransactionExecutor 实现)。
     * 3. 根据本地事务的结果，向 Broker 发送 commit 或 rollback 指令。
     * </p>
     *
     * @param message  要发送的原始消息。
     * @param executor 本地事务执行器，包含了业务方的核心业务逻辑。
     * @param arg      传递给本地事务执行器的额外参数。
     * @return 事务发送的结果，包含了事务ID和最终状态。
     * @throws SnackMQClientException 如果在任何步骤中发生不可恢复的错误。
     */
    TransactionSendResult sendMessageInTransaction(Message message, LocalTransactionExecutor executor, Object arg) throws SnackMQClientException;

    /**
     * 设置事务状态回查监听器。
     * <p>
     * 当 Broker 长时间未收到一个 "半消息" 的二次确认时，它会主动向生产者发起回查请求。
     * 生产者客户端在收到回查请求后，会调用此监听器来确定原始本地事务的最终状态。
     * </p><p>
     * <b>重要:</b> 任何使用事务消息的生产者都必须实现并设置此监听器，否则无法处理事务悬挂问题。
     * </p>
     *
     * @param listener 业务方实现的监听器。
     */
    void setTransactionStateListener(TransactionStateListener listener);
}